package com.baseframe.auth.utils;

import com.baseframe.auth.entity.UserBean;
import com.baseframe.jwt.utils.JwtUtil;
import com.baseframe.tool.container.Kv;
import com.baseframe.tool.utils.redis.CommonRedisUtil;
import io.jsonwebtoken.Claims;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class TokenUtil {
    public static final String CLIENT_ID = "client_id";
    public static final String USER_ID="user_id";
    public static final String USER_NAME="user_name";
    public static final String ROLE_ID="role_id";
    public static final String DETAILS="details";
    public static final int AUTH_LENGTH = 7;

    public static final String AUTHORITIES = "authorities";
    public static final String TOKEN_PREFIX = "Bearer ";

    public static final String AUTHORIZATION = "Authorization";

    static String ACCESS_TOKEN_KEY = "base:oauth:token:";
    static String REFRESH_TOKEN_KEY = "base:oauth:refreshToken:";


    /**
     * 获取jwt令牌
     * @param authorization 有前缀的令牌
     * @return jwt
     */
    public static String stripOffPrefixes(String authorization){
        String token = null;
        if ((authorization != null) && (authorization.length() > AUTH_LENGTH)) {
            token = authorization.substring(AUTH_LENGTH);
        }
        return token;
    }

    /**
     * 解析jwt令牌
     * @param token 令牌
     * @return 用户对象
     */
    @SuppressWarnings({"unchecked"})
    public static UserBean parse(String token) {
        try {
            Claims claims = JwtUtil.getClaims(token);
            UserBean userBean = new UserBean();

            String clientId = claims.get(CLIENT_ID, String.class);
            if (clientId!=null){
                userBean.setClientId(clientId);
            }
            Long userId = claims.get(USER_ID, Long.class);
            if (userId != null) {
                userBean.setUserId(userId);
            }
            String username = claims.get(USER_NAME, String.class);
            if (username != null) {
                userBean.setUsername(username);
            }
            Long roleId = claims.get(ROLE_ID, Long.class);
            if (roleId != null) {
                userBean.setRoleId(roleId);
            }

            Object authorities = claims.get(AUTHORITIES);
            if (authorities instanceof ArrayList<?>) {
                List<String> authoritiesList = (List<String>) authorities;
                userBean.setAuthorities(authoritiesList);
            }

            Kv details = Kv.create().setAll((Map<? extends String, ?>) claims.get(DETAILS));
            userBean.setDetails(details);

            return userBean;
        } catch (Exception e) {
           e.printStackTrace();

           return null;

        }

    }


    /**
     * 将令牌添加到redis中
     * @param accessToken 用户令牌
     * @param refreshToken 刷新令牌
     * @param expires 过期时间
     * @param single 是否支持同时一人在线
     */
    public static  void addToken2Redis(String accessToken,String refreshToken,int expires,boolean single){
        if (single){
            UserBean userBean = parse(accessToken);

            deleteToken(userBean.getUserId());

            CommonRedisUtil.setValue(ACCESS_TOKEN_KEY+userBean.getUserId(),accessToken, (long) expires, TimeUnit.SECONDS);
            CommonRedisUtil.setValue(REFRESH_TOKEN_KEY+userBean.getUserId(),refreshToken, (long) expires*168, TimeUnit.SECONDS);


        }else {
            String jwtKeyRedis2AccessToken = JwtUtil.getJwtId(accessToken);
            String jwtKeyRedis2RefreshToken = JwtUtil.getJwtId(refreshToken);
            CommonRedisUtil.setValue(ACCESS_TOKEN_KEY+jwtKeyRedis2AccessToken,accessToken, (long) expires, TimeUnit.SECONDS);
            CommonRedisUtil.setValue(REFRESH_TOKEN_KEY+jwtKeyRedis2RefreshToken,refreshToken, (long) expires*168, TimeUnit.SECONDS);

        }

    }

    /**
     * 获取redis中的token
     * @param redisKey redis中的key
     * @return 令牌
     * @param <T> 对象泛型
     */
    public static<T> String getAccessToken(T redisKey){
        return CommonRedisUtil.getValue(ACCESS_TOKEN_KEY+redisKey);
    }

    /**
     * 获取redis中的刷新令牌
     * @param redisKey redis中的key
     * @return 刷新令牌
     * @param <T> 对象泛型
     */
    public static<T> String getRefreshToken(T redisKey){
        return CommonRedisUtil.getValue(REFRESH_TOKEN_KEY+redisKey);
    }


    /**
     * 删除redis只能的token
     * @param redisKey redis中的key
     * @param <T> 对象泛型
     */
    public static<T> boolean  deleteToken(T redisKey){

       return CommonRedisUtil.delete(REFRESH_TOKEN_KEY+redisKey)&&CommonRedisUtil.delete(ACCESS_TOKEN_KEY+redisKey);


    }




}
